//
// Created by abstergo on 2024/2/23.
//

#ifndef TBS_CPP_OPTIONAL_HPP
#define TBS_CPP_OPTIONAL_HPP
#include <base/base.hpp>

namespace tbs {
template<typename T> class Optional;

struct null_opt {
  explicit constexpr null_opt() = default;

};

// 定义一个模板类Optional，用于表示一个可能包含值或不包含值的类型
template<typename T> class Optional {
public:
  // 定义一个别名_transform_function，用于表示转换函数的类型
  template<class TF> using _transform_function = std::function<Optional<TF>(Optional<T> &)>;

  // 重载解引用运算符，返回存储的值的引用
  T &operator*();

  // 构造函数，接受一个常量引用作为参数，初始化Optional对象
  Optional(CONST T &v);

  // 构造函数，接受一个右值引用作为参数，初始化Optional对象
  Optional(T &&v);

  // 默认构造函数，初始化一个不包含值的Optional对象
  Optional();

  // 移动构造函数，接受一个右值引用作为参数，用于快速转移资源
  Optional(Optional &&other) NO_EXCEPT;

  // 复制构造函数，接受一个常量引用作为参数，用于复制Optional对象
  Optional(CONST Optional &other);

  // 构造函数，接受一个null_opt常量引用作为参数，初始化一个不包含值的Optional对象
  Optional(CONST null_opt &nop);

  // 移动构造函数，接受一个null_opt右值引用作为参数，用于快速转移资源
  Optional(null_opt &&op) NO_EXCEPT;

  // 隐式转换运算符，允许Optional对象在需要bool类型的地方被使用
  operator bool() CONST;

  // 检查Optional对象是否包含一个值
  bool has_value() CONST NO_EXCEPT;

  // 复制赋值运算符，用于复制其他Optional对象的值
  CONST_EXP Optional &operator=(const Optional &other);

  // 移动赋值运算符，用于快速转移其他Optional对象的资源
  CONST_EXP Optional &operator=(Optional &&other) NO_EXCEPT;

  // 赋值运算符，用于将null_opt的值赋给Optional对象
  CONST_EXP Optional &operator=(null_opt &&other) NO_EXCEPT;

  // 赋值运算符，用于将null_opt的常量引用值赋给Optional对象
  CONST_EXP Optional &operator=(CONST null_opt &other) NO_EXCEPT;

  // 获取Optional对象中的值，如果对象不包含值，则抛出异常
  CONST_EXP T &value() &;

  // 获取Optional对象中的值，如果对象不包含值，则抛出异常，常量成员函数版本
  CONST_EXP CONST T &value() CONST &;

  // 获取Optional对象中的值，如果对象不包含值，则抛出异常，右值引用版本
  CONST_EXP T &&value() &&;

  // 获取Optional对象中的值，如果对象不包含值，则抛出异常，常量成员函数右值引用版本
  CONST_EXP CONST T &&value() CONST &&;

  // 如果Optional对象不包含值，则返回默认值t
  CONST_EXP T value_or(T &&t) CONST NO_EXCEPT;

  // 如果Optional对象不包含值，则调用函数f并返回结果
  template<class F> CONST_EXP T func_or(F &&f) CONST NO_EXCEPT;

  // 重置Optional对象，使其不包含任何值
  void reset();

  // 使用转换函数f将Optional对象转换为其他类型
  template<class TF> Optional<TF> transform(_transform_function<TF> f);

  // 在Optional对象中构造一个新值，接受一个右值引用作为参数
  void emplace(T &&val);

  // 在Optional对象中构造一个新值，接受一个常量引用作为参数
  void emplace(CONST T &val);

private:
  T _val; // 存储的值
  bool _has_value = false; // 标记Optional对象是否包含一个值
};

#include "inls/base/optional.cuh"
}

#endif //TBS_CPP_OPTIONAL_HPP
